Uurige JavaScripti sulundeid praktiliste nÀidete kaudu, mÔistes nende toimimist ja reaalseid rakendusi tarkvaraarenduses.
JavaScripti sulundid: DemĂŒstifitseerimine praktiliste nĂ€idetega
Sulundid (closures) on JavaScripti pĂ”himĂ”tteline kontseptsioon, mis tekitab sageli segadust igas tasemes arendajates. Sulundite mĂ”istmine on ĂŒlioluline tĂ”husa, hooldatava ja turvalise koodi kirjutamiseks. See pĂ”hjalik juhend demĂŒstifitseerib sulundid praktiliste nĂ€idete abil ja demonstreerib nende reaalseid rakendusi.
Mis on sulund?
Lihtsamalt öeldes on sulund funktsiooni ja leksikaalse keskkonna kombinatsioon, milles see funktsioon deklareeriti. See tĂ€hendab, et sulund vĂ”imaldab funktsioonil pÀÀseda juurde muutujatele oma ĂŒmbritsevast skoobist, isegi pĂ€rast seda, kui vĂ€line funktsioon on oma töö lĂ”petanud. MĂ”elge sellest kui sisemisest funktsioonist, mis "mĂ€letab" oma keskkonda.
Selle tÔeliseks mÔistmiseks jaotame lahti pÔhikomponendid:
- Funktsioon: Sisemine funktsioon, mis on osa sulundist.
- Leksikaalne keskkond: Ămbritsev skoop, kus funktsioon deklareeriti. See hĂ”lmab muutujaid, funktsioone ja muid deklaratsioone.
Maagia toimub seetÔttu, et sisemine funktsioon sÀilitab juurdepÀÀsu oma leksikaalse skoobi muutujatele isegi pÀrast seda, kui vÀlimine funktsioon on tagastatud. See kÀitumine on JavaScripti skoobi ja mÀlu haldamise pÔhiosa.
Miks on sulundid olulised?
Sulundid ei ole pelgalt teoreetiline kontseptsioon; need on hÀdavajalikud paljude levinud programmeerimismustrite jaoks JavaScriptis. Need pakuvad jÀrgmisi eeliseid:
- Andmete kapseldamine: Sulundid vÔimaldavad teil luua privaatseid muutujaid ja meetodeid, kaitstes andmeid vÀlise juurdepÀÀsu ja muutmise eest.
- OlekusÀilitus: Sulundid sÀilitavad muutujate oleku funktsioonikÔnede vahel, mis on kasulik loendurite, taimerite ja muude olekupÔhiste komponentide loomiseks.
- KÔrgemat jÀrku funktsioonid: Sulundeid kasutatakse sageli koos kÔrgemat jÀrku funktsioonidega (funktsioonid, mis vÔtavad argumentidena teisi funktsioone vÔi tagastavad funktsioone), vÔimaldades vÔimsa ja paindliku koodi loomist.
- AsĂŒnkroonne JavaScript: Sulunditel on kriitiline roll asĂŒnkroonsete operatsioonide, nĂ€iteks tagasikutsete (callbacks) ja lubaduste (promises) haldamisel.
JavaScripti sulundite praktilised nÀited
Sukeldume mÔnedesse praktilistesse nÀidetesse, et illustreerida, kuidas sulundid töötavad ja kuidas neid saab kasutada reaalsetes stsenaariumides.
NĂ€ide 1: Lihtne loendur
See nÀide demonstreerib, kuidas sulundit saab kasutada loenduri loomiseks, mis sÀilitab oma oleku funktsioonikÔnede vahel.
function createCounter() {
let count = 0;
return function() {
count++;
console.log(count);
};
}
const increment = createCounter();
increment(); // VĂ€ljund: 1
increment(); // VĂ€ljund: 2
increment(); // VĂ€ljund: 3
Selgitus:
createCounter()on vĂ€limine funktsioon, mis deklareerib muutujacount.- See tagastab sisemise funktsiooni (antud juhul anonĂŒĂŒmse funktsiooni), mis suurendab
countvÀÀrtust ja logib selle konsooli. - Sisemine funktsioon moodustab sulundi muutuja
countĂŒle. - Isegi pĂ€rast seda, kui
createCounter()on oma töö lÔpetanud, sÀilitab sisemine funktsioon juurdepÀÀsu muutujalecount. - Iga
increment()kutse suurendab samacountmuutujat, demonstreerides sulundi vÔimet olekut sÀilitada.
NĂ€ide 2: Andmete kapseldamine privaatsete muutujatega
Sulundeid saab kasutada privaatsete muutujate loomiseks, kaitstes andmeid otsejuurdepÀÀsu ja muutmise eest vÀljaspool funktsiooni.
function createBankAccount(initialBalance) {
let balance = initialBalance;
return {
deposit: function(amount) {
balance += amount;
return balance; //Tagastatakse demonstreerimiseks, vÔiks olla ka void
},
withdraw: function(amount) {
if (amount <= balance) {
balance -= amount;
return balance; //Tagastatakse demonstreerimiseks, vÔiks olla ka void
} else {
return "Insufficient funds.";
}
},
getBalance: function() {
return balance;
}
};
}
const account = createBankAccount(1000);
console.log(account.deposit(500)); // VĂ€ljund: 1500
console.log(account.withdraw(200)); // VĂ€ljund: 1300
console.log(account.getBalance()); // VĂ€ljund: 1300
// Otse saldole ligipÀÀsemine ei toimi
// console.log(account.balance); // VĂ€ljund: undefined
Selgitus:
createBankAccount()loob pangakonto objekti meetoditega raha sissekandmiseks, vÀljavÔtmiseks ja saldo saamiseks.- Muutuja
balanceon deklareeritudcreateBankAccount()skoobis ja pole vÀljastpoolt otse ligipÀÀsetav. - Meetodid
deposit,withdrawjagetBalancemoodustavad sulundid muutujabalanceĂŒle. - Need meetodid saavad muutujat
balancelugeda ja muuta, kuid muutuja ise jÀÀb privaatseks.
NĂ€ide 3: Sulundite kasutamine setTimeout'iga tsĂŒklis
Sulundid on hĂ€davajalikud asĂŒnkroonsete operatsioonidega töötamisel, nagu setTimeout, eriti tsĂŒklites. Ilma sulunditeta vĂ”ite kohata ootamatut kĂ€itumist JavaScripti asĂŒnkroonse olemuse tĂ”ttu.
for (var i = 1; i <= 5; i++) {
(function(j) {
setTimeout(function() {
console.log("Value of i: " + j);
}, j * 1000);
})(i);
}
// VĂ€ljund:
// Value of i: 1 (pÀrast 1 sekundit)
// Value of i: 2 (pÀrast 2 sekundit)
// Value of i: 3 (pÀrast 3 sekundit)
// Value of i: 4 (pÀrast 4 sekundit)
// Value of i: 5 (pÀrast 5 sekundit)
Selgitus:
- Ilma sulundita (kohe vÀljakutsutav funktsiooniavaldis ehk IIFE) viitaksid kÔik
setTimeouttagasikutsed lĂ”puks samaleimuutujale, mille lĂ”ppvÀÀrtus oleks pĂ€rast tsĂŒkli lĂ”ppu 6. - IIFE loob iga tsĂŒkli iteratsiooni jaoks uue skoobi, pĂŒĂŒdes kinni
ihetkevÀÀrtuse parameetrisj. - Iga
setTimeouttagasikutse moodustab sulundi muutujajĂŒle, tagades, et see logib iga iteratsiooni jaoks Ă”igeivÀÀrtuse.
Kasutades tsĂŒklis let mĂ€rksĂ”na var asemel, lahendaks see samuti probleemi, kuna let loob iga iteratsiooni jaoks plokiskoobi.
for (let i = 1; i <= 5; i++) {
setTimeout(function() {
console.log("Value of i: " + i);
}, i * 1000);
}
// VĂ€ljund (sama mis ĂŒlal):
// Value of i: 1 (pÀrast 1 sekundit)
// Value of i: 2 (pÀrast 2 sekundit)
// Value of i: 3 (pÀrast 3 sekundit)
// Value of i: 4 (pÀrast 4 sekundit)
// Value of i: 5 (pÀrast 5 sekundit)
NĂ€ide 4: Karritamine (Currying) ja osaline rakendamine (Partial Application)
Sulundid on karritamise ja osalise rakendamise aluseks. Need on tehnikad, mida kasutatakse mitme argumendiga funktsioonide muutmiseks funktsioonide jadaks, millest igaĂŒks vĂ”tab ĂŒhe argumendi.
function multiply(a) {
return function(b) {
return function(c) {
return a * b * c;
};
};
}
const multiplyBy5 = multiply(5);
const multiplyBy5And2 = multiplyBy5(2);
console.log(multiplyBy5And2(3)); // VĂ€ljund: 30 (5 * 2 * 3)
Selgitus:
multiplyon karritatud funktsioon, mis vĂ”tab kolm argumenti, ĂŒhe korraga.- Iga sisemine funktsioon moodustab sulundi oma vĂ€limise skoobi muutujate (
a,b) ĂŒle. multiplyBy5on funktsioon, kusavÀÀrtuseks on juba seatud 5.multiplyBy5And2on funktsioon, kusaon 5 jabon 2.- Viimane kutse
multiplyBy5And2(3)lÔpetab arvutuse ja tagastab tulemuse.
NĂ€ide 5: Moodulimuster
Sulundeid kasutatakse laialdaselt moodulimustris, mis aitab organiseerida ja struktureerida JavaScripti koodi, edendades modulaarsust ja vÀltides nimekonflikte.
const myModule = (function() {
let privateVariable = "Hello, world!";
function privateMethod() {
console.log(privateVariable);
}
return {
publicMethod: function() {
privateMethod();
},
publicProperty: "This is a public property."
};
})();
console.log(myModule.publicProperty); // VĂ€ljund: This is a public property.
myModule.publicMethod(); // VĂ€ljund: Hello, world!
// Otse privateVariable vÔi privateMethod ligipÀÀsemine ei toimi
// console.log(myModule.privateVariable); // VĂ€ljund: undefined
// myModule.privateMethod(); // VĂ€ljund: TypeError: myModule.privateMethod is not a function
Selgitus:
- IIFE loob uue skoobi, kapseldades
privateVariablejaprivateMethod. - Tagastatud objekt paljastab ainult
publicMethodjapublicProperty. publicMethodmoodustab sulundiprivateMethodjaprivateVariableĂŒle, vĂ”imaldades neile juurdepÀÀsu ka pĂ€rast IIFE tĂ€itmist.- See muster loob tĂ”husalt mooduli privaatsete ja avalike liikmetega.
Sulundid ja mÀluhaldus
Kuigi sulundid on vĂ”imsad, on oluline olla teadlik nende potentsiaalsest mĂ”just mĂ€luhaldusele. Kuna sulundid sĂ€ilitavad juurdepÀÀsu oma ĂŒmbritseva skoobi muutujatele, vĂ”ivad nad takistada nende muutujate prĂŒgikoristust, kui neid enam ei vajata. See vĂ”ib hooletu kĂ€sitsemise korral pĂ”hjustada mĂ€lulekkeid.
MÀlulekete vÀltimiseks veenduge, et katkestate kÔik mittevajalikud viited muutujatele sulundites, kui neid enam ei vajata. Seda saab teha, seades muutujate vÀÀrtuseks null vÔi restruktureerides oma koodi, et vÀltida mittevajalike sulundite loomist.
Levinud vead sulunditega, mida vÀltida
- Leksikaalse skoobi unustamine: Pidage alati meeles, et sulund hÔlmab keskkonda *selle loomise hetkel*. Kui muutujad muutuvad pÀrast sulundi loomist, peegeldab sulund neid muudatusi.
- Mittevajalike sulundite loomine: VÀltige sulundite loomist, kui neid pole vaja, kuna need vÔivad mÔjutada jÔudlust ja mÀlukasutust.
- Muutujate lekitamine: Olge teadlik sulundite poolt hÔivatud muutujate elueast ja veenduge, et need vabastatakse, kui neid enam ei vajata, et vÀltida mÀlulekkeid.
KokkuvÔte
JavaScripti sulundid on vĂ”imas ja hĂ€davajalik kontseptsioon, mida iga JavaScripti arendaja peab mĂ”istma. Need vĂ”imaldavad andmete kapseldamist, oleku sĂ€ilitamist, kĂ”rgemat jĂ€rku funktsioone ja asĂŒnkroonset programmeerimist. MĂ”istes, kuidas sulundid töötavad ja kuidas neid tĂ”husalt kasutada, saate kirjutada tĂ”husamat, hooldatavamat ja turvalisemat koodi.
See juhend on andnud pĂ”hjaliku ĂŒlevaate sulunditest koos praktiliste nĂ€idetega. Nende nĂ€idetega harjutades ja katsetades saate sĂŒvendada oma arusaama sulunditest ja saada osavamaks JavaScripti arendajaks.
Lisalugemist
- Mozilla Developer Network (MDN): Sulundid - https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures
- You Don't Know JS: Scope & Closures, autor Kyle Simpson
- Avastage veebipÔhiseid kodeerimisplatvorme nagu CodePen ja JSFiddle, et katsetada erinevate sulundite nÀidetega.